package com.crm.system.service.impl.enterpriseWechat;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.crm.common.constant.EnterpriseWechatParameters;
import com.crm.model.entity.enterpriseWechat.Token;
import com.crm.redis.RedisPrefix;
import com.crm.redis.mapper.ValueRMapper;
import com.crm.system.service.enterpriseWechat.EnterpriseWechatService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.net.ssl.HttpsURLConnection;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @ Author ：pym
 * @ Date   ：2021/9/16 11:13
 */
@Slf4j
@Service
public class EnterpriseWechatServiceImpl implements EnterpriseWechatService {
    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 获取企业微信用户邮箱
     * @Author pym
     * @Date  2021/9/17 15:00
     * @param code 通过成员授权获取到的code，最大为512字节。每次成员授权带上的code将不一样，code只能使用一次，5分钟未被使用自动过期。
     * @param i i access_token无效，重新获取一次
     * @return {@link {java.lang.String}}
     */
    @Override
    public String getEmail(String code, int i) {
        String email = "";
        String accessToken = getAccessToken();
        log.info("EnterpriseWechatServiceImpl getEmail accessToken---------------------" + accessToken);
        log.info("EnterpriseWechatServiceImpl getEmail code----------------------------" + code);
        if (StringUtils.isNotBlank(accessToken) && StringUtils.isNotBlank(code)) {
            String userInfoUrl = EnterpriseWechatParameters.getUserInfoUrl.replace("ACCESS_TOKEN", accessToken).replace("CODE", code);
            StringBuilder userInfoResult = getResult(userInfoUrl);
            log.info("EnterpriseWechatServiceImpl getEmail getUserInfo----------------------result: " + userInfoResult);
            JSONObject userInfo = JSON.parseObject(userInfoResult.toString());
            String userId = userInfo.getString("UserId");
            int errcode = userInfo.getIntValue("errcode");
            if (errcode == 0) {
                if (StringUtils.isNotBlank(userId)) {
                    String userUrl = EnterpriseWechatParameters.getUserUrl.replace("ACCESS_TOKEN", accessToken).replace("USERID", userId);
                    StringBuilder userResult = getResult(userUrl);
                    log.info("EnterpriseWechatServiceImpl getEmail getUser--------------------------result: " + userResult);
                    JSONObject user = JSON.parseObject(userResult.toString());
                    email = user.getString("email");
                }
            } else if (errcode == 40014) {//invalid access_token
                if (i == 0) {
                    return email;
                }
                i--;
                ValueRMapper.delRedis(redisTemplate, RedisPrefix.ACCESS_TOKEN_KEY);
                getEmail(code, i);
            }
        }
        return email;
    }

    /**
     * 获取access_token，先去Redis去取，Redis没有就重新获取
     * @Author pym
     * @Date  2021/9/17 15:00
     * @param
     * @return {@link {java.lang.String}}
     */
    private String getAccessToken(){
        String accessToken = "";
        Token token = ValueRMapper.getRedisObject(redisTemplate, RedisPrefix.ACCESS_TOKEN_KEY, Token.class);
        /*SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String createTm = token.getCreateTm();
        long time = sdf.parse(createTm).getTime();
        long now = System.currentTimeMillis();
        long interval = (now - time) / 1000;
        // 超过7200秒，重新获取accessToken
        if (interval > 7200) {

        }*/
        if (Objects.nonNull(token)) {
            accessToken = token.getAccess_token();
        } else {
            String accessTokenUrl = EnterpriseWechatParameters.getAccessTokenUrl.replace("ID",EnterpriseWechatParameters.corpId).replace("SECRET",EnterpriseWechatParameters.secret);
            String result = getResult(accessTokenUrl).toString();
            log.info("EnterpriseWechatServiceImpl getAccessToken----------------------result: " + result);
            Token tokenB = getToken(result);
            accessToken = tokenB.getAccess_token();
            ValueRMapper.setRedisObject(redisTemplate, RedisPrefix.ACCESS_TOKEN_KEY, tokenB, 7200, TimeUnit.SECONDS);
        }
        return accessToken;
    }

    /**
     * 获取请求结果
     * @Author pym
     * @Date  2021/9/17 15:02
     * @param url 请求Url
     * @return {@link {java.lang.StringBuilder}}
     */
    private StringBuilder getResult(String url) {
        StringBuilder result = new StringBuilder();
        BufferedReader in = null;
        try {
            URL urlN = new URL(url);
            HttpsURLConnection conn = (HttpsURLConnection) urlN.openConnection();
            conn.connect();
            in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
            String line;
            while ((line = in.readLine()) != null) {
                result.append(line);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return result;
    }

    /**
     * 获取access_token实体
     * @Author pym
     * @Date  2021/9/17 15:03
     * @param result 请求结果
     * @return {@link {com.crm.model.entity.enterpriseWechat.Token}}
     */
    private Token getToken(String result) {
        JSONObject jsonObject = JSON.parseObject(result);
        Token token = new Token();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String createTm = sdf.format(new Date());
        token.setAccess_token(jsonObject.getString("access_token"));
        token.setErrcode(jsonObject.getIntValue("errcode"));
        token.setErrmsg(jsonObject.getString("errmsg"));
        token.setExpires_in(jsonObject.getString("expires_in"));
        token.setCreateTm(createTm);
        return token;
    }

}
